package com.espirit.eap.util.tagAdaptor;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import com.espirit.eap.manager.I18nService;
import com.espirit.eap.pagelayout.BlockSection;
import com.espirit.eap.pagelayout.Element;
import com.espirit.eap.pagelayout.ElementService;
import com.espirit.eap.pagelayout.Layout;
import com.espirit.eap.pagelayout.PageCache;
import com.espirit.eap.pagelayout.TagInfo;
import com.espirit.eap.util.TaglibManager;
import com.espirit.eap.util.TxFileService;
import com.googlecode.cswish.Config;

@Service
public class TagBlockSectionAdaptor implements TagElementAdaptor<BlockSection> {
	
	private static final Log logger = LogFactory.getLog(TagBlockSectionAdaptor.class);
	
	@Resource
	private TagAdaptorUtil tagAdaptorUtil;
	
	@Resource
	private I18nService i18nService;
	
	@Resource
	private TaglibManager tagManager;
	
	@Resource
	private Config config;
	
	@Resource
	private TxFileService txFileService;
	
	@Resource
	private ElementService elementService;
	
	@Override
	public TagInfo getTagProperties(Layout root, BlockSection element, Map<String, Object> context) {
		BlockSection blockSection =element;
		TagInfo tagInfo = new TagInfo(true);
		tagInfo.setContainer(true);
		String tagName = blockSection.getTagName();
		if (tagName == null) {
			tagName = "container";
		}
		tagInfo.setTagName(tagName);
		Map<String, Object> properties = tagInfo.getTagProperties();
		properties.put("columnCount", blockSection.getColsPerRow());
		Integer id = blockSection.getId();
		if (id != null && id < 0) {
			id = -id;
		}
		
		String name = tagAdaptorUtil.getName(element);
		properties.put("name", name);
		String namePrefix = blockSection.getNamePrefix();
		properties.put("namePrefix", namePrefix);
		properties.put("positionCol", blockSection.getPositionCol());
		
		String i18n = element.getI18n();
		if (i18n != null) {
			properties.put("label", i18n);
		}

		// extra properties
		Map<String, String> exProperties = blockSection.getExProperties();
		if (exProperties != null) {
			properties.putAll(exProperties);
		}
		return tagInfo;
	}
	
	@Override
	public String getTagName(BlockSection element) {
		String tagName = element.getTagName();
		if (tagName == null) {
			return "container";
		} else {
			return tagName;
		}
	}

	@Override
	public BlockSection updateToElement(Map<String, String> tagProperties, BlockSection existed, Map<String, Object> context, PageCache pageCache) {
		BlockSection blockSection = existed;
		
		String tagName = tagProperties.get("tagName");
		if (TAG_TEMPLATE.equals(tagName)) {
			String url = tagProperties.get("url");
			if (url != null && url.length() > 0) {
				// add placeholder element
				List<Element> children = blockSection.getSortChildren();
				if (children == null) {
					children = blockSection.safeChildren();
				}
				int childrenLength = children.size();
				
				try {
					String template = txFileService.read(null, url);
					if (template == null) {
						template = "";
					}
					
					String[] blocks = StringUtils.splitByWholeSeparator(template, "[var]");
					int varCount = blocks.length - 1;
					if (varCount > childrenLength) {
						for (int i = 0, gap = varCount - childrenLength; i < gap; i++) {
							Map<String, Object> properties = new HashMap<String, Object>();
							BlockSection bs = addElement(blockSection, "layout", properties, pageCache);
							bs.addExProperty("clazz", "jlayout-inline");
							bs.setPositionCol(childrenLength + i);
						}
					} else if (childrenLength > varCount) {
						for (int i = childrenLength - 1; i >= varCount; i--) {
							children.remove(i);
						}
					}
				} catch (Exception ex) {
					logger.error("Failed to reald template tag: " + url, ex);
				}
			}			
		}
		
		// column count
		String value = tagProperties.get("columnCount");
		if (isNotEmpty(value)) {
			int newColumnCount = new Integer(value);
			int oldColumnCount = blockSection.getColsPerRow();
			if (newColumnCount - oldColumnCount < 0) {
				// rebuild the column count if the column space is not enough
				if (blockSection.getChildren() != null) {
					for (Element se : blockSection.getChildren()) {
						Integer col = se.getPositionCol();
						if (col != null && col >= newColumnCount) {
							se.setPositionCol(newColumnCount - 1);
						}
					}
				}
			}
		}
		
		// label
		tagAdaptorUtil.updateLabel(tagProperties, existed, pageCache);
		Map<String, Object> defaultTagProperties = (Map<String, Object>) context.get(DEFAULT_TAG_PROP);
		tagAdaptorUtil.updateElement(tagProperties, defaultTagProperties, blockSection);
		
		return blockSection;
	}
	
	private boolean isNotEmpty(String value) {
		return value != null && value.length() > 0;
	}

	@Override
	public BlockSection addElement(Element parent, String tagName, Map<String, Object> properties, PageCache pageCache) {
		BlockSection blockSection = new BlockSection();
		Integer index = pageCache.increaseMaxId();
		blockSection.setId(-index);
		
		Layout root = pageCache.getLayout();
		tagAdaptorUtil.addToParent(blockSection, root, parent, properties);
		blockSection.setColsPerRow(2);
		blockSection.setTagName(tagName);
		
		// name
		String name = tagAdaptorUtil.createName(root, tagName);
		blockSection.setName(name);
		
		if (tagManager.getDefaultTagProperty(pageCache.getLayout().getCategories(), tagName).containsKey("namePrefix")) {
			String namePrefix = tagAdaptorUtil.getNamePrefix(parent);
			
			if (namePrefix == null) {
//				boolean isRead = RestAction.isRead(pageCache.getInvoker().methodName);
				blockSection.setNamePrefix("model");
//				if (isRead) {
//					blockSection.setNamePrefix("execute");
//				}
			}
		}
		
		// i18n
		if (blockSection.getI18n() == null) {
			blockSection.setI18n(tagName);
		}
		
		// special logic for the layout
		if ("layout".equals(tagName)) {
			blockSection.setColsPerRow(1);
		} else if ("template".equals(tagName)) {
			// special logic for the template, see TagPageReferenceAdaptor.addElement
			// TODO: move it to tagAdaptorUtil?
			String modelPath = pageCache.getPath();
			String url = tagAdaptorUtil.createTemplatePath(root, modelPath);
			blockSection.addExProperty("url", url);
		}
		
		return blockSection;
	}

	@Override
	public void deleteElement(Element parent, BlockSection existed, PageCache pageCache) {
	}
};
